package moltencore.network.protocol;

import moltencore.game.Field;
import moltencore.game.Player;
import moltencore.game.bubble.Bubble;
import spark.math.Vector2;
import spark.network.Util;
import spark.network.protocol.Base;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.LinkedList;

public class FieldLayout extends Base {
	public static final short TYPE = 0x58;
	private static final byte[] TYPE_BYTES = Util.makeBytes(TYPE);

	private long fieldId;
	private final static int FIELD_ID_LENGTH = Long.SIZE / 8;
	// implied
	//private byte fieldFileLength;
	private final static int FIELD_FILE_LENGTH_LENGTH = Byte.SIZE / 8;
	private byte[] fieldFile;

	private byte bubblesCount;
	private final static int BUBBLES_COUNT_LENGTH = Byte.SIZE / 8;

	private GridBubbleData[] gridBubblesData;

	protected static final int SIZE =
			Base.SIZE +
			FIELD_ID_LENGTH +
			FIELD_FILE_LENGTH_LENGTH +
			BUBBLES_COUNT_LENGTH;

	public FieldLayout() {
		super(true, TYPE_BYTES);
	}

	public FieldLayout(Field field) {
		this();
		this.setFieldId(field.getFieldId());
		this.setFieldFile(field.getFieldFile());
		LinkedList<GridBubbleData> gridBubbles = new LinkedList<GridBubbleData>();
		for(Bubble bubble : field.getAttachedBubbles().getBubbles()) {
			gridBubbles.add(new GridBubbleData(bubble));
		}
		this.setGridBubblesData(gridBubbles.toArray(new GridBubbleData[gridBubbles.size()]));
	}

	public long getFieldId() {
		return fieldId;
	}

	public void setFieldId(long fieldId) {
		this.fieldId = fieldId;
	}

	public GridBubbleData[] getGridBubblesData() {
		return gridBubblesData;
	}

	public void setGridBubblesData(GridBubbleData[] gridBubblesData) {
		this.gridBubblesData = gridBubblesData;
		this.bubblesCount = (byte)gridBubblesData.length;
	}

	@Override
	public void getBytes(byte[] buffer) {
		super.getBytes(buffer);
		ByteBuffer bb = ByteBuffer.wrap(buffer, Base.SIZE, buffer.length - Base.SIZE);
		bb.put(Util.makeBytes(fieldId));
		bb.put((byte)fieldFile.length);
		bb.put(fieldFile);
		bb.put((byte)gridBubblesData.length);
		for(GridBubbleData gridBubbleData : gridBubblesData) {
			gridBubbleData.getBytes(bb.array(), bb.position());
			bb.position(bb.position() + GridBubbleData.SIZE);
		}
	}

	@Override
	public void fill(byte[] buffer) {
		super.fill(buffer);
		ByteBuffer bb = ByteBuffer.wrap(buffer, Base.SIZE, buffer.length - Base.SIZE);
		fieldId = bb.getLong();
		fieldFile = new byte[bb.get()];
		bb.get(fieldFile, 0, fieldFile.length);
		bubblesCount = bb.get();
		gridBubblesData = new GridBubbleData[bubblesCount];
		for(int i = 0; i < gridBubblesData.length; i++) {
			gridBubblesData[i] = new GridBubbleData();
			gridBubblesData[i].fill(bb.array(), bb.position());
			bb.position(bb.position() + GridBubbleData.SIZE);
		}
	}

	@Override
	public int getSize() {
		return SIZE + fieldFile.length + bubblesCount * GridBubbleData.SIZE;
	}

	public static FieldLayout create(byte[] buffer, long receiveTime) {
		FieldLayout packet = new FieldLayout();
		packet.fill(buffer);
		return packet;
	}

	public void setFieldFile(String fieldFile) {
		this.fieldFile = fieldFile.getBytes();
	}

	public String getFieldFile() {
		return new String(fieldFile);
	}
}